// RUN: circt-opt --pass-pipeline='builtin.module(kanagawa-add-operator-library, kanagawa.design(kanagawa.class(kanagawa.method.df(kanagawa.sblock.isolated(pipeline-schedule-linear)))))' %s | \
// RUN:   FileCheck %s

// CHECK-LABEL:   ssp.library @kanagawa_operator_library {
// CHECK:           operator_type @comb.add [latency<1>]
// CHECK:           operator_type @comb.sub [latency<1>]
// CHECK:           operator_type @comb.mul [latency<2>]
// CHECK:           operator_type @comb.mods [latency<2>]
// CHECK:           operator_type @comb.modu [latency<2>]
// CHECK:           operator_type @comb.and [latency<0>]
// CHECK:           operator_type @comb.or [latency<0>]
// CHECK:           operator_type @comb.xor [latency<0>]
// CHECK:           operator_type @comb.icmp [latency<1>]
// CHECK:           operator_type @comb.shl [latency<0>]
// CHECK:           operator_type @comb.shru [latency<0>]
// CHECK:           operator_type @comb.shrs [latency<1>]
// CHECK:         }

// CHECK:           kanagawa.class sym @SchedulePipeline {
// CHECK:             kanagawa.method.df @foo(%[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32)  -> i32 {
// CHECK:               %[[VAL_2:.*]] = kanagawa.sblock.isolated (%[[VAL_3:.*]] : i32 = %[[VAL_0]], %[[VAL_4:.*]] : i32 = %[[VAL_1]]) -> i32 {
// CHECK:                 %[[VAL_5:.*]], %[[VAL_6:.*]], %[[VAL_7:.*]], %[[VAL_8:.*]] = kanagawa.pipeline.header
// CHECK:                 %[[VAL_9:.*]], %[[VAL_10:.*]] = pipeline.scheduled(%[[VAL_11:.*]] : i32 = %[[VAL_3]], %[[VAL_12:.*]] : i32 = %[[VAL_4]]) stall(%[[VAL_8]]) clock(%[[VAL_5]]) reset(%[[VAL_6]]) go(%[[VAL_7]]) entryEn(%[[VAL_13:.*]])  -> (out0 : i32) {
// CHECK:                   %[[VAL_14:.*]] = comb.mul %[[VAL_11]], %[[VAL_12]] {ssp.operator_type = @comb.mul} : i32
// CHECK:                   pipeline.stage ^bb1
// CHECK:                 ^bb1(%[[VAL_15:.*]]: i1):
// CHECK:                   %[[VAL_16:.*]] = pipeline.src %[[VAL_11]] : i32
// CHECK:                   %[[VAL_17:.*]] = pipeline.src %[[VAL_12]] : i32
// CHECK:                   %[[VAL_18:.*]] = comb.add %[[VAL_16]], %[[VAL_17]] {ssp.operator_type = @comb.add} : i32
// CHECK:                   pipeline.stage ^bb2
// CHECK:                 ^bb2(%[[VAL_19:.*]]: i1):
// CHECK:                   %[[VAL_20:.*]] = pipeline.src %[[VAL_18]] : i32
// CHECK:                   %[[VAL_21:.*]] = pipeline.src %[[VAL_14]] : i32
// CHECK:                   %[[VAL_22:.*]] = comb.sub %[[VAL_20]], %[[VAL_21]] {ssp.operator_type = @comb.sub} : i32
// CHECK:                   pipeline.stage ^bb3
// CHECK:                 ^bb3(%[[VAL_23:.*]]: i1):
// CHECK:                   %[[VAL_24:.*]] = pipeline.src %[[VAL_22]] : i32
// CHECK:                   %[[VAL_25:.*]] = pipeline.src %[[VAL_18]] : i32
// CHECK:                   %[[VAL_26:.*]] = comb.mul %[[VAL_24]], %[[VAL_25]] {ssp.operator_type = @comb.mul} : i32
// CHECK:                   pipeline.stage ^bb4
// CHECK:                 ^bb4(%[[VAL_27:.*]]: i1):
// CHECK:                   pipeline.stage ^bb5
// CHECK:                 ^bb5(%[[VAL_28:.*]]: i1):
// CHECK:                   %[[VAL_29:.*]] = pipeline.src %[[VAL_26]] : i32
// CHECK:                   pipeline.return %[[VAL_29]] : i32
// CHECK:                 }
// CHECK:                 kanagawa.sblock.return %[[VAL_30:.*]] : i32
// CHECK:               }
// CHECK:               kanagawa.return %[[VAL_2]] : i32
// CHECK:             }
// CHECK:           }

kanagawa.design @foo {
kanagawa.class sym @SchedulePipeline {
  // A test wherein the returned values are either a value generated by an
  // operation in the pipeline, or a value that's passed through the pipeline.
  // The resulting IR should have all values passing through the newly created
  // pipeline.
  kanagawa.method.df @foo(%a: i32, %b: i32) -> (i32) {
    %0 = kanagawa.sblock.isolated (%arg2 : i32 = %a, %arg3 : i32 = %b) -> i32 {
      %clock, %reset, %go, %stall = kanagawa.pipeline.header
      %out0, %done = pipeline.unscheduled(%in0 : i32 = %arg2, %in1 : i32 = %arg3) stall(%stall) clock(%clock) reset(%reset) go(%go) entryEn(%s0_enable)  {operator_lib = @kanagawa_operator_library} -> (out0 : i32) {
        %1 = comb.add %in0, %in1 {ssp.operator_type = @comb.add} : i32
        %2 = comb.mul %in0, %in1 {ssp.operator_type = @comb.mul} : i32
        %3 = comb.sub %1, %2 {ssp.operator_type = @comb.sub} : i32
        %4 = comb.mul %3, %1 {ssp.operator_type = @comb.mul} : i32
        pipeline.return %4 : i32
      }
      kanagawa.sblock.return %out0 : i32
    }
    kanagawa.return %0 : i32
  }
}
}
